/**
 * @fileOverview
 *
 *
 *
 * @author: techird
 * @copyright: Baidu FEX, 2014
 */

// define(function (require, exports, module) {
/*!
    * https://github.com/Starcounter-Jack/Fast-JSON-Patch
    * json-patch-duplex.js 0.5.0
    * (c) 2013 Joachim Wester
    * MIT license
    */

var _objectKeys = (function () {
  if (Object.keys)
    return Object.keys;

  return function (o) {
    var keys = [];
    for (var i in o) {
      if (o.hasOwnProperty(i)) {
        keys.push(i);
      }
    }
    return keys;
  };
})();
function escapePathComponent(str) {
  if (str.indexOf('/') === -1 && str.indexOf('~') === -1)
    return str;
  return str.replace(/~/g, '~0').replace(/\//g, '~1');
}
function deepClone(obj) {
  if (typeof obj === "object") {
    return JSON.parse(JSON.stringify(obj));
  } else {
    return obj;
  }
}

// Dirty check if obj is different from mirror, generate patches and update mirror
function _generate(mirror, obj, patches, path) {
  var newKeys = _objectKeys(obj);
  var oldKeys = _objectKeys(mirror);
  var changed = false;
  var deleted = false;

  for (var t = oldKeys.length - 1; t >= 0; t--) {
    var key = oldKeys[t];
    var oldVal = mirror[key];
    if (obj.hasOwnProperty(key)) {
      var newVal = obj[key];
      if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null) {
        _generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key));
      } else {
        if (oldVal != newVal) {
          changed = true;
          patches.push({
            op: "replace",
            path: path + "/" + escapePathComponent(key),
            value: deepClone(newVal)
          });
        }
      }
    } else {
      patches.push({
        op: "remove",
        path: path + "/" + escapePathComponent(key)
      });
      deleted = true; // property has been deleted
    }
  }

  if (!deleted && newKeys.length == oldKeys.length) {
    return;
  }

  for (var t = 0; t < newKeys.length; t++) {
    var key = newKeys[t];
    if (!mirror.hasOwnProperty(key)) {
      patches.push({
        op: "add",
        path: path + "/" + escapePathComponent(key),
        value: deepClone(obj[key])
      });
    }
  }
}

export default function compare(tree1, tree2) {
  var patches = [];
  _generate(tree1, tree2, patches, '');
  return patches;
}

// return module.exports = compare;
// });
//
